#pragma once

#include<thread>
#include<mutex>
#include<queue>
#include<functional>
#include<condition_variable>
#include<vector>
#include<future>


class ThreadPool
{
private:
    /* data */
    //存储共有多少个线程
    std::vector<std::thread> threds;
    //存储任务
    std::queue<std::function<void()>> tasks;
    // 防止读取任务的时候发生碰撞，加个互斥锁
    std::mutex task_mutex;
    std::condition_variable cv;
    bool stop;

public:
    ThreadPool(int size = std::thread::hardware_concurrency());
    ~ThreadPool();

    void addFunc(std::function<void()>);

    void stopPool();

    template<class F,class... Args>
    auto addFunc(F && f, Args &&... args)->std::future<typename std::result_of<F(Args...)>::type>;
};

template <class F, class... Args>
inline auto ThreadPool::addFunc(F &&f, Args &&...args) -> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;
    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f),std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex>lock(task_mutex);
        if(stop){
            throw std::runtime_error(" stopped ThreadPool");
        }
        tasks.emplace([task](){(*task)();});
    }
    cv.notify_one();
    return res;
}
